﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace daSyntaxAnalyser.SyntaxTree
{
    // Объекты
    using daBase.Objects;
    using daBase.Objects.Safe;

    /// <summary>
    /// Элемент-файл (модуль, библиотека, программа)
    /// </summary>
    public class FileElement : SyntaxTreeElement
    {
        // Путь, имя, модули и бит сохранения
        protected string path;
        protected IdElement name;
        protected UsesElement uses;
        private bool analysed, saved;

        /// <summary>
        /// Путь файла
        /// </summary>
        public string Path { get { return path; } set { path = value; } }

        /// <summary>
        /// Имя
        /// </summary>
        public IdElement Name { get { return name; } set { name = value; } }

        /// <summary>
        /// Подключаемые модули
        /// </summary>
        public UsesElement Uses { get { return uses; } set { uses = value; } }

        /// <summary>
        /// Флаг - проанализирован
        /// </summary>
        public bool Analysed { get { return analysed; } set { analysed = value; } }

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="Path">Путь</param>
        /// <param name="Name">Имя</param>
        /// <param name="Uses">Подключаемые модули</param>
        public FileElement(TokenInfo StartInfo, string Path, IdElement Name, UsesElement Uses, List<TokenInfo> Comments)
            : base(StartInfo, Comments)
        {
            name = Name;
            uses = Uses;
            path = Path;
            analysed = saved = false;
        }

        protected override IEnumerator<ISyntaxTreeElement> CreateEnumerator()
        {
            yield return name;
            if (uses != null)
                yield return uses;
        }

        private delegate void ToDo(UseElement Use);

        private void DoRecursive(UsesElement Uses, ToDo ToDoRecursive)
        {
            if ((Uses != null) && (Uses.Uses != null))
                foreach (UseElement use in Uses)
                    ToDoRecursive(use);
        }

        protected void RecursiveSaveTo(UsesElement Uses, string Directory)
        {
            DoRecursive(Uses, u =>
            {
                if (u.TreeRoot != null) 
                    u.TreeRoot.Root.SaveTo(
                        (u.In == null)
                        ?
                        Directory
                        :
                        new FileInfo(string.Format("{0}\\{1}", Directory, SyntaxTreeElement.TranslateString(u.In.Tokens))).DirectoryName
                );
            });
        }

        protected void RecursiveReset(UsesElement Uses)
        {
            DoRecursive(Uses, u => { if (u.TreeRoot != null)u.TreeRoot.Root.Reset(); });
        }

        protected virtual void SaveMe(string AsFile)
        {
            SafeFile.WriteAllText(AsFile, ToString());
            RecursiveSaveTo(uses, new FileInfo(AsFile).DirectoryName);
        }

        public void SaveTo(string Directory)
        {
            if (!saved)
            {
                saved = true;
                SaveMe(string.Format("{0}\\{1}", Directory, path));
            }
        }

        protected virtual void ResetMe()
        {
            saved = false;
            analysed = false;
            RecursiveReset(uses);
        }

        public void Reset()
        {
            if (saved)
                ResetMe();
        }
    }
}
